package com.xy.order.utils;

import org.jsoup.Connection;
import org.jsoup.Jsoup;
import org.jsoup.internal.StringUtil;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.List;
import java.util.stream.Collectors;

public class NorvelUtils {

    static class novel {

        //封面路径
        private String bookImage;

        //路径
        private String bookUrl;

        //书名
        private String bookName;

        //作者
        private String bookAuthor;

        //简介
        private String bookInfo;

        //类型
        private String bookType;

        //阅读量
        private Long visitCount;


        public String getBookImage() {
            return bookImage;
        }

        public void setBookImage(String bookImage) {
            this.bookImage = bookImage;
        }

        public String getBookUrl() {
            return bookUrl;
        }

        public void setBookUrl(String bookUrl) {
            this.bookUrl = bookUrl;
        }

        public String getBookName() {
            return bookName;
        }

        public void setBookName(String bookName) {
            this.bookName = bookName;
        }

        public String getBookAuthor() {
            return bookAuthor;
        }

        public void setBookAuthor(String bookAuthor) {
            this.bookAuthor = bookAuthor;
        }

        public String getBookInfo() {
            return bookInfo;
        }

        public void setBookInfo(String bookInfo) {
            this.bookInfo = bookInfo;
        }

        public String getBookType() {
            return bookType;
        }

        public void setBookType(String bookType) {
            this.bookType = bookType;
        }

        public Long getVisitCount() {
            return visitCount;
        }

        public void setVisitCount(Long visitCount) {
            this.visitCount = visitCount;
        }
    }

    //爬虫目标网站的网站名
    private static String novel_name = "";


    //获取搜索栏的url地址，拼接关键字进行检索
    private static String searchUrl = "http://www.iktxt.com/search.html?keywords=";

    //获取小说网页的url地址
    private static String bookUrl = "http://www.iktxt.com";

    //获取阅读地址的url地址
    private static String readUrl = "http://www.iktxt.com";


    //输出文件名称(一般为书名)
    private static String fileName = "";

    //空格，四格位置
    private static String space = "    ";

    //文件输出流
    private static FileWriter writer;

    //计数器
    private static int pageCount = 1;

    public static void main(String[] args) throws IOException {
        parse("音综直播，你唱儿歌");
    }

    /**
     * 执行程序
     *
     * @param keyword
     * @throws IOException
     */
    public static void parse(String keyword) throws IOException {
        //输入关键字获取图书信息
        List<novel> novelList = getBookList(keyword);

        //初始化程序
        getWriter();
        long l = System.currentTimeMillis();
        String url = novelList.get(0).bookUrl;
        if (novelList != null) {
            //循环爬取小说
            do {
                Element element = nextPage(url);
                outputToFile(element);
                url = hasNext(element);
            } while (url != null);
            writer.close();
            long time = (System.currentTimeMillis() - l) / 1000;
            System.out.println("\n\n 成功爬取所有章节！耗时" + time + "秒");
        }
    }


    /**
     * 获取图书信息
     *
     * @param keyword 搜索关键字
     * @throws IOException
     */
    public static List<novel> getBookList(String keyword) throws IOException {
        //拼接搜索栏URL地址
        searchUrl = searchUrl + keyword;
        //获取当前搜索结果页
        Elements elements = nextPage(searchUrl).getElementsByClass("rt_750 f-lt");

        List<Element> elementList = elements.stream().collect(Collectors.toList());

        novel novel = new novel();
        //获取封面
        List<novel> novelList = elementList.stream().map(
                element -> {
                    //获取封面
                    String imageUrl = element
                            .getElementsByTag("img")
                            .attr("src");
                    //设置封面
                    novel.setBookImage(imageUrl);

                    //获取路径
                    String path = element
                            .getElementsByClass("t")
                            .get(0).getElementsByTag("a")
                            .attr("href");
                    //设置路径
                    try {
                        String readPath = getReadPath(bookUrl + path);
                        novel.setBookUrl(readPath);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }

                    //获取书名
                    String book_name = element
                            .getElementsByClass("t")
                            .get(0)
                            .getElementsByTag("span")
                            .text();
                    //设置书名
                    fileName = book_name;
                    novel.setBookName(book_name);

                    //获取作者
                    String author = element
                            .getElementsByClass("author")
                            .get(0)
                            .getElementsByTag("span")
                            .text();
                    //设置作者
                    novel.setBookAuthor(author);

                    //获取简介
                    String info = element
                            .getElementsByClass("intro")
                            .text();
                    //设置简介
                    novel.setBookInfo(info);

                    //获取类型
                    String type = element
                            .getElementsByClass("author")
                            .get(0)
                            .getElementsByTag("a")
                            .text();
                    //设置类型
                    novel.setBookType(type);

                    //获取阅读量
                    Long visitCount = Long.valueOf(element
                            .getElementsByClass("update")
                            .get(0)
                            .getElementsByTag("small")
                            .text()
                            .replace("阅读(", "")
                            .replace(")", ""));
                    //设置阅读量
                    novel.setVisitCount(visitCount);

                    return novel;
                }
        ).collect(Collectors.toList());
        System.out.println("novelList = " + novelList);
        return novelList;
    }

    /**
     * 获取阅读地址URL
     *
     * @param url 搜索之后的url
     * @return 阅读地址URL
     */
    public static String getReadPath(String url) throws IOException {
        String path = nextPage(url)
                .getElementsByClass("item")
                .get(0)
                .getElementsByTag("a")
                .attr("href");
        return readUrl + path;
    }


    //获取输出流
    public static void getWriter() throws IOException {
        String path = "D:/" + fileName + ".txt";
        File file = new File(path);
        if (file.exists()) {
            System.out.println("目标书籍已存在!请修改文件名或删除原书籍 " + path);
            System.exit(0);
        }
        writer = new FileWriter(file);
    }


    //爬取页面
    private static Element nextPage(String url) throws IOException {
        // 获取连接实例，伪造浏览器身份
        Connection conn = Jsoup.connect(url)
                .header("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9")
                .header("Accept-Encoding", "gzip, deflate")
                .header("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6")
                .header("Cache-Control", "max-age=0")
                .header("Connection", "keep-alive")
                .header("Host", url)
                .header("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36 Edg/88.0.705.56");
        return conn.execute().parse().body();
    }

    //获取当前章节标题
    private static String getTitle(Element element) {
        String title = element.select(".title h1").text();
        if (StringUtil.isBlank(title)) {
            return title;
        }
        return title;
    }

    //获取章节具体内容
    public static String getContent(Element element) {
        String content = element
                .getElementsByClass("entry content_yh")
                .get(0)
                .getElementsByTag("p")
                .html();
        return content;
    }

    //是否有下一页?有的话返回下一页的URL地址，没有就返回NULL
    private static String hasNext(Element element) {

        //获取下一章的地址
        String attr = element
                .getElementsByClass("page_box")
                .get(0)
                .getElementsByTag("li")
                .get(2)
                .getElementsByTag("a")
                .attr("onclick")
                .replace("window.location.href='", "")
                .replace("'", "");
        //通过观察存在下一章的时候URL会以.html结尾，不存在时会跳转到首页，通过这个特点判断是否存在下一章
        System.out.println("attr = " + attr);
        return readUrl + attr;
    }


    //输出到文件
    public static void outputToFile(Element element) throws IOException {
        String title = getTitle(element);
        String content = getContent(element);
        String text = space + title + "\r\n\r\n" + content;
        writer.write(text);
        writer.flush();
        System.out.printf("===>[%s]爬取完成，正在爬取下一章(第%d次操作)", title, pageCount++);
    }


}